/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "场景.h"
#include "面/面.h"
#include "物体/S_摄像机.h"
#include "core/引擎配置.h"
#include "材质/预设材质.h"
#include "纹理/纹理.h"

#include <几何图形/图形相交.h>
#include <场景/intern/S_Scene.h>


static std::map<uint32, S_Scene*> g场景容器;
static C_Key分配器                g场景ID分配器;



S_Scene* f_scene_创建(S_设备环境& ctx, uint32 key) {
	key = g场景ID分配器.f_Gen();
	S_Scene* scene = new S_Scene(key);
	scene->m_Ctx = ctx;

	scene->m_默认渲染世界 = f_world_创建渲染世界(ctx);
	f_world_添加渲染层(scene->m_默认渲染世界, f_ob_创建渲染层(ctx), 0);

	g场景容器[key] = scene;
	return scene;
}

void f_scene_销毁(uint32 key) {
	if (g场景容器.find(key) != g场景容器.end()) {
		delete g场景容器[key];

		g场景ID分配器.f_Move(key);
		g场景容器.erase(key);
	}
}

void f_scene_销毁2(S_Scene* scene) {
	f_world_销毁渲染世界(scene->m_默认渲染世界);

	if (g场景容器.find(scene->m_ID) != g场景容器.end()) {
		f_scene_销毁(scene->m_ID);
	}
}

S_Scene* f_scene_get场景(uint32 key) {
	if (g场景容器.find(key) != g场景容器.end()) {
		return g场景容器[key];
	}
	return nullptr;
}

void f_scene_创建世界(S_Scene* scene) {
	S_Mesh* me = f_surface_创建网格对象(scene->m_Ctx, E_网格数据枚举::e_Mesh_Vulkan);


	DEF_3Fs 顶点;
	DEF_3Fs 法线;
	DEF_2Fs UV;
	DEF_Is 索引;
	f_graph_构建球体(128, 64, 10, 顶点, 法线, UV, 索引);

	std::vector<S_VNTC> vnData;
	f_surface_数组合并(vnData, 顶点, 法线, UV);





	return;
	scene->m_天空 = f_ob_创建(scene->m_Ctx, E_物体类型::t_网格物体);
	f_ob_set数据槽数量(scene->m_天空, 1);
	f_ob_set数据(scene->m_天空, me);
	f_ob_set颜色2(scene->m_天空, { 10,10,10,255 }, 0);

	

	//std::vector<S_VNT1> vnData;
	//f_surface_数组合并(vnData, 顶点, 法线, UV);
	//f_mesh_fill顶点数据(me, vnData);
	//f_mesh_fill索引数据(me, 索引);
	//f_mesh_计算包围盒(me);
	//f_surface_计算三角形边相邻面索引(me);
	//
	//scene->m_天空默认材质 = new S_面基本光照材质(scene->m_Ctx);
	//f_ob_set材质(scene->m_天空, scene->m_天空默认材质, 0);
	//f_me_alloc多维材质槽(me, 1, scene->m_天空默认材质);
	//f_mesh_set绘制内存属性(me, {});

}

void f_scene_渲染(S_Scene* scene) {

}

void f_scene_渲染世界(S_Scene* scene, const S_渲染参数& 渲染参数) {
	if (scene->m_天空) {
		f_ob_绘制单个元素(scene->m_天空, 渲染参数, 0, false);
	}
}

void f_scene_添加物体列表(S_Scene* scene, S_物体* ob) {
	switch (ob->m_Type) {
	case E_物体类型::t_多边形:
	case E_物体类型::t_网格物体:
	case E_物体类型::t_空:
		scene->m_物体_向全局内存过渡.push_back(ob);

		ob->m_isUpdate = true;
		ob->m_UpdateGPU参数布局 = true;
	default:
		break;
	}
}

void f_scene_场景链接物体(uint32 sceneID, uint32 objectID) {

}

void f_scene_场景链接物体(S_Scene* scene, S_物体* object) {
	scene->m_物体.push_back(object);
}

void f_scene_添加物体(S_Scene* scene, S_物体* ob, E_场景物体容器类型 容器类型) {
	scene->f_add物体({ ob }, 容器类型);
}

void f_scene_添加物体(S_Scene* scene, const std::vector<S_物体*>& ob) {
	scene->f_add物体(ob, E_场景物体容器类型::e_集合);
}

void f_scene_移除物体(S_Scene* scene, S_物体* ob) {
	scene->f_remove物体(ob, E_场景物体容器类型::e_集合);
}

void f_scene_移除物体(S_Scene* scene, const std::vector<S_物体*>& ob) {
	scene->f_remove物体(ob, E_场景物体容器类型::e_集合);
}

void f_scene_移除所有物体(S_Scene* scene, E_场景物体容器类型 容器类型) {
	switch (容器类型) {
		case e_链表:
			break;
		case e_数组:
			break;
		case e_映射:
			
			break;
		case e_集合:
			scene->m_物体set.clear();
			break;
		default:
			break;
	}
	
}

std::set<S_物体*>& f_scene_get集合物体(S_Scene* scene) {
	return scene->m_物体set;
}

std::list<S_物体*>& f_scene_get循序物体(S_Scene* scene) {
	return scene->m_物体;
	// TODO: 在此处插入 return 语句
}



void f_scene_开启光追(S_Scene* scene, S_设备环境& ctx) {
	
	S_着色器创建配置 图元配置 = {
			{
				{0, E_着色阶段::e_光追射线生成 | E_着色阶段::e_光追最近相交, E_板载缓存类型::e_光追BVH},

				{1, E_着色阶段::e_光追射线生成, E_板载缓存类型::e_IMAGE},

				{DEF_BINDING_Render_Camera, E_着色阶段::e_光追射线生成 | E_着色阶段::e_光追AABB , E_板载缓存类型::e_SSBO},

				{DEF_ObMeshBindID, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追AABB | E_着色阶段::e_光追回调, E_板载缓存类型::e_SSBO},

				{DEF_MaterialsBindID, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_SSBO},

				{DEF_TexturesBindID, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调, E_板载缓存类型::e_SAMPLER_Array},

				{DEF_RenderFrameBindID, E_着色阶段::e_光追射线生成 | E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追AABB | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_UBO},

				{DEF_ParallelLightBindID, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_SSBO},

				{DEF_BINDING_Render_Geom, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_SSBO},

				{DEF_BINDING_Render_GlobalParam, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_SSBO},

				{DEF_BINDING_RayArrayTexturesBindID, E_着色阶段::e_光追最近相交 | E_着色阶段::e_光追回调 | E_着色阶段::e_光追忽略相交, E_板载缓存类型::e_SAMPLER_Array},

				{DEF_BINDING_RayTexturesWriteLayers, E_着色阶段::e_光追射线生成, E_板载缓存类型::e_IMAGE_Array},

			},
			{
			},
			{
				{S_引擎配置::m_3D着色器文件根路径 + "物理光照_光线生成.spv", {}, E_着色阶段::e_光追射线生成},
				{S_引擎配置::m_3D着色器文件根路径 + "物理光追_光线忽略.spv", {}, E_着色阶段::e_光追忽略相交},
				//{S_引擎配置::m_3D着色器文件根路径 + "光追_AABB.rispv", {}, E_着色阶段::e_光追AABB},
				{S_引擎配置::m_3D着色器文件根路径 + "物理辐射光照_最近相交.spv", {}, E_着色阶段::e_光追最近相交},
			}
	};

	scene->m_光追后端 = f_df_create光追后端(ctx, 图元配置);
	if (ctx.m_支持光追) {
		scene->m_光追顶层加速结构 = f_bm_alloc(f_buf_getGlobal().g_TLAS_0, 0);
		scene->m_光追网格对象 = f_bm_alloc(f_buf_getGlobal().g_RtMesh, 0);
		std::cout << "ray render device OK" << std::endl;
	}
	
}

void f_scene_销毁光追渲染器(S_Scene* scene) {
	f_df_销毁光追后端(scene->m_光追后端);

}

void f_scene_重构光追线管(S_Scene* scene, S_设备环境& ctx) {

}

void f_scene_添加光追材质着色器(S_Scene* scene, const std::string path, int32 loc) {
	if (loc >= 0 && loc + E_光追阶段ID::e_光追阶段ID_材质回调 < scene->m_光追后端->m_线管创建配置信息.m_Paths.size()) {
		loc += E_光追阶段ID::e_光追阶段ID_材质回调;
		scene->m_光追后端->m_线管创建配置信息.m_Paths[loc] = { path, {}, E_着色阶段::e_光追回调 };
	}
	else {
		scene->m_光追后端->m_线管创建配置信息.m_Paths.push_back({path, {}, E_着色阶段::e_光追回调 });
	}
	scene->m_光追后端->m_重新编译线管 = true;
}

void f_scene_删除光追材质着色器(S_Scene* scene, int32 loc) {
	if (loc >= 0 && loc + E_光追阶段ID::e_光追阶段ID_材质回调 < scene->m_光追后端->m_线管创建配置信息.m_Paths.size()) {
		scene->m_光追后端->m_线管创建配置信息.m_Paths.erase(scene->m_光追后端->m_线管创建配置信息.m_Paths.begin() + loc);
	}
	else {
		scene->m_光追后端->m_线管创建配置信息.m_Paths.pop_back();
	}
	scene->m_光追后端->m_重新编译线管 = true;
}

void f_scene_更新物体渲染(S_Scene* scene, S_物体* object) {
	scene->f_更新渲染物体();
}

void f_scene_设置光追渲染采样(S_Scene* scene, S_RayRenderAttr& Attr) {
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_BouncesNum = Attr.反弹次数;
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_LigthSamples = Attr.光采样;
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_SamplesNum = Attr.采样次数;
}

void f_scene_设置环境着色器(S_Scene* scene, int32 环境着色器ID) {
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_world_ShaderID = 环境着色器ID;
}

void f_scene_设置光追渲染器视口渲染(S_Scene* scene, bool 是否渲染) {
	scene->m_光追后端->m_渲染 = 是否渲染;
}

void f_scene_重载渲染器绑定纹理(S_Scene* scene, S_纹理* tex) {
	uint32 num = S_光追后端::G纹理.size();
	auto* data = S_光追后端::G纹理.data();

	//static std::mutex g分配内存锁;
	//g分配内存锁.lock();
	scene->m_光追后端->f_set纹理(tex);

	//for (uint32 i = 0; i < num; ++i) {
	//	if (data[i].m_Ptr == tex) {
	//		S_纹理* t = (S_纹理*)data[i].m_Ptr;
	//		scene->m_光追后端->f_set纹理(t, t->m_TexID);
	//		break;
	//	}
	//}
	//g分配内存锁.unlock();
}

void f_scene_更新配置内部纹理(S_Scene* scene) {
	scene->m_光追后端->m_重新设置内部纹理传入参数 = true;
}

void f_连接物理引擎车辆操控函数(S_Scene* scene, fun_物体async_p f) {
	scene->m_Physics.m_Bullet->mf_车辆操作更新 = f;
}

void f_连接渲染前更新函数(S_Scene* scene, fun_渲染前更新p f) {
	scene->mf_渲染前Update = f;
}




static uint32 g网格数据层索引[3] = { E_物体网格元素类型::e_MT_框, E_物体网格元素类型::e_MT_面, E_物体网格元素类型::e_MT_边 };
static uint8 g网格拾取模式[3] = { 1, 0, 1 };

std::vector<S_物体*> f_scene_射线拾取(S_Scene* scene, const vec3& s, const vec3& dir, const S_摄像机& camera, const S_Rect2Df& rect, const vec2& 屏幕坐标, float32* 最近坐标) {
	std::vector<S_物体*> pickObjs;
	
	vec3 交点 = {};
	vec3 相机位置 = s;
	S_物体拾取信息 物体拾取信息{ nullptr, -1, 100000000, 6 };

	if (camera.m_投影模式 == E_投影模式::e_正交) {
		相机位置 = -相机位置;
	}


	//S_物体* 拾取物体 = nullptr;
	for (auto& ob : scene->m_物体set) {
		//if (ob->m_可拾取 && !ob->m_父物体) {
		if (ob->m_可拾取) {
			
			switch (ob->m_Type) {
				//case E_物体类型::t_包: 
				case E_物体类型::t_线段: {
					for (uint32 k = 0; k < ob->m_DataNum; ++k) {
						auto* m = f_ob_getMesh(ob, k);
						auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, m, nullptr, camera, rect, 屏幕坐标, 0, 相机位置);

						f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					}
					break;
				}

				case E_物体类型::t_点光源:
				case E_物体类型::t_聚光灯:
				case E_物体类型::t_平行光:
				case E_物体类型::t_区域光:
				case E_物体类型::t_灯光:
				case E_物体类型::t_虚拟体: {
					uint32 网格层数量 = DEF_Min(1, ob->m_DataNum);
					for (uint32 k = 0; k < ob->m_DataNum; ++k) {
						auto* m = f_ob_getMesh(ob, k);
						auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, m, nullptr, camera, rect, 屏幕坐标, k, 相机位置);

						f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					}
					break;
				}
				case E_物体类型::t_骨架:
				case E_物体类型::t_骨骼: {
					uint32 槽数量 = ob->m_DataNum > 2 ? 2 : 1;
					uint32 网格槽ID[2] = { E_物体网格元素类型::e_MT_框, E_物体网格元素类型::e_MT_边 };
					auto 变换矩阵 = f_ob_get变换矩阵(ob, ob->m_实例ID);

					for (uint32 k = 0; k < 槽数量; ++k) {
						auto* m = f_ob_getMesh(ob, 网格槽ID[k]);
						auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, m, nullptr, camera, rect, 屏幕坐标, 网格槽ID[k], 相机位置);

						f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					}
					break;
				}
				case E_物体类型::t_空间曲线: {
					auto* m = f_ob_getMesh(ob, 0);
					auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, m, nullptr, camera, rect, 屏幕坐标, 1, 相机位置);

					f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					break;
				}
				default: {
					uint32 网格层数量 = DEF_Min(3, ob->m_DataNum);

					if (网格层数量) {
						for (uint32 k = 0; k < 网格层数量; ++k) {
							if (f_ob_显示模式是否开启(ob, g网格数据层索引[k])) {

								auto* m = f_ob_getMesh(ob, g网格数据层索引[k]);
								auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, m, nullptr, camera, rect, 屏幕坐标, g网格数据层索引[k], 相机位置);

								f_scene_对比拾取信息(物体拾取信息, 新拾取, g网格拾取模式[k]);
							}
						}
					}
					else {
						auto 新拾取 = f_scene_射线拾取物体(ob, s, dir, nullptr, nullptr, camera, rect, 屏幕坐标, E_物体网格元素类型::e_MT_面, 相机位置);

						f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					}
					break;
				}
			}
		}
	}

	if (物体拾取信息.物体) {
		pickObjs.push_back(物体拾取信息.物体);

		if (最近坐标) {
			(*最近坐标) = 物体拾取信息.相交深度;
		}
	}
	
	//pickObjs = {};
	return pickObjs;
}

void f_scene_框选物体(S_物体* 待选物体, std::set<S_物体*>& 选择物体, const vec4 平面[5], const vec3 视锥[4][2]) {
	auto* ob_ptr = 待选物体->m_子物体.data();
	uint32 num = 待选物体->m_子物体.size();
	for (uint32 i = 0; i < num; ++i) {
		f_scene_框选物体(static_cast<S_物体*>(ob_ptr[i]), 选择物体, 平面, 视锥);
	}

	if(!待选物体->m_可拾取) return;


	uint32 槽 = 0;
	switch (待选物体->m_Type) {
		
		case E_物体类型::t_网格物体:
		case E_物体类型::t_多边形: {
			const auto& 网格包 = f_ob_get数据(待选物体, 0);

			auto mat = f_ob_getMatrix(待选物体, 待选物体->m_实例ID);

			if (f_surface_框选包围盒(待选物体->m_包围盒, _Vec3(mat.m3), 平面, 视锥)) {
				bool 有拾取 = f_surface_框选面(网格包.m_Mesh, mat, 平面, 视锥);
				if (有拾取) 选择物体.insert(待选物体);
			}

			槽 = E_物体网格元素类型::e_MT_面;
			break;
		}
		
		default:
			break;
	}
	if(待选物体->m_是否实例) return;

}

void f_scene_框选物体(S_物体* 待选物体, std::set<S_物体*>& 选择物体, const Mat44f 相机矩阵[2], const S_Rect2Df& view, const S_Bounding2& 框) {
	
	待选物体->m_包围盒;
	auto cube = 待选物体->m_包围盒;
	auto matxx = f_ob_getMatrix(待选物体, 待选物体->m_实例ID);
	cube.pos += _Vec3(matxx.m3);

	//vec2 rectPoints[4] = {
	//	框.min,
	//	{框.max.x, 框.min.y},
	//	框.max,
	//	{框.min.x, 框.max.y}
	//};

	if (f_surface_框选包围盒(cube, 相机矩阵, view, 框)) {
		const auto& 网格包 = f_ob_get数据(待选物体);

		if (f_surface_屏幕拾取网格(网格包.m_Mesh, matxx, 相机矩阵, view, 框)) {
			选择物体.insert(待选物体);
		}
	}

}

void f_scene_拾取包围盒物体(std::set<S_物体*>& 选择物体, S_物体* 待选物体, const vec3 视线起点方向相机位置[3]) {
	
	if (待选物体->m_显示 && !待选物体->m_根实例 && 待选物体->m_可拾取) {
		//auto modelMat = f_ob_get变换矩阵(待选物体);
		float32 线拾取距离 = vec_len(视线起点方向相机位置[2] - 待选物体->m_包围盒.pos) * 0.1;
		vec3 size = 待选物体->m_包围盒.size;

		float32 距离 = f_graph_点到直线距离(视线起点方向相机位置[0], 视线起点方向相机位置[1], 待选物体->m_包围盒.pos);
		float32 包围盒半径 = vec_Max(vec_abs(size)) * 1.3;
		if (距离 <= 包围盒半径 + 线拾取距离) {
			选择物体.insert(待选物体);
		}
	}

	for (auto& e : 待选物体->m_子物体) {
		f_scene_拾取包围盒物体(选择物体, static_cast<S_物体*>(e), 视线起点方向相机位置);
	}

}

S_物体拾取信息 f_scene_拾取物体网格(S_物体* 待选物体, uint32 槽, const vec3 视线起点方向相机位置[3], const S_摄像机& camera) {
	S_Mesh* me = f_ob_getMesh(待选物体, 槽);

	S_物体拾取信息 物体拾取信息 = { nullptr, -1, 100000000, 1e+7 };
	if(!me->m_拾取) return 物体拾取信息;

	Mat44f mat[2] = {f_ob_get变换矩阵(待选物体, 待选物体->m_实例ID), camera.m_相机逆矩阵 };

	float32 当前拾取距离 = 100000000;
	vec3 交点{};
	
	float32 线拾取距离 = vec_len(视线起点方向相机位置[2] - 待选物体->m_包围盒.pos) * 0.1;
	vec3 相机位置 = f_camera_get眼睛位置(camera);
	if (camera.m_投影模式 == E_投影模式::e_正交) {
		//相机位置 = -相机位置;
	}

	switch (待选物体->m_Type) {

		//case E_物体类型::t_骨节:
		case E_物体类型::t_骨架:
		case E_物体类型::t_骨骼:
			S_面拾取 拾取信息;
			if (me->m_索引->m_Mem.m_数量 > 10000) {
				拾取信息 = f_surface_Gpu射线拾取面(me, 视线起点方向相机位置[0], 视线起点方向相机位置[1], mat, 相机位置);
				
			}
			else {
				拾取信息 = f_surface_射线面相交(me, mat, 视线起点方向相机位置[0], 视线起点方向相机位置[1], 相机位置);
				
			}
			if (拾取信息.相交宽度 >= 0) {
				物体拾取信息.相交深度 = 拾取信息.相交宽度;
				物体拾取信息.实例ID = 槽;
				物体拾取信息.物体 = 待选物体;
			}
			break;


		case E_物体类型::t_骨节:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体:
		
			//if (ob->m_变换矩阵.m_Mem.m_大小 > 1) break;
		case E_物体类型::t_实例: {

			switch (槽) {
				case E_物体网格元素类型::e_MT_焦点:
				case E_物体网格元素类型::e_MT_面: {
					S_面拾取 拾取信息;
					if (me->m_索引->m_Mem.m_数量 > 10000) {
						拾取信息 = f_surface_Gpu射线拾取面(me, 视线起点方向相机位置[0], 视线起点方向相机位置[1], mat, 相机位置);
					}
					else {
						拾取信息 = f_surface_射线面相交(me, mat, 视线起点方向相机位置[0], 视线起点方向相机位置[1], 相机位置);
					}

					if (拾取信息.面索引 >= 0) {
						S_物体拾取信息 新拾取;
						新拾取.相交深度 = 拾取信息.相交宽度;
						新拾取.平面距离 = -1;
						新拾取.实例ID = 待选物体->m_实例ID;
						新拾取.物体 = 待选物体;

						f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
					}
					break;
				}
				case E_物体网格元素类型::e_MT_框: {
					S_线拾取 拾取信息 = f_surface_线段相交(me, mat, 视线起点方向相机位置[0], 视线起点方向相机位置[1], 当前拾取距离, 待选物体->m_实例ID);
					if (拾取信息.相交宽度 < 线拾取距离) {
						物体拾取信息.相交深度 = 当前拾取距离;
						物体拾取信息.实例ID = 待选物体->m_实例ID;
						物体拾取信息.物体 = 待选物体;
					}
					break;
				}
				default:
					break;
			}
			break;
		}

		case E_物体类型::t_灯光:
		case E_物体类型::t_点光源:
		case E_物体类型::t_平行光:
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光:
		case E_物体类型::t_虚拟体: {
			S_线拾取 info = f_surface_线段相交(me, mat, 视线起点方向相机位置[0], 视线起点方向相机位置[1], 当前拾取距离, 待选物体->m_实例ID);
			if (info.相交宽度 < 线拾取距离) {
				物体拾取信息.相交深度 = info.相交宽度;
				物体拾取信息.实例ID = 待选物体->m_实例ID;
				物体拾取信息.物体 = 待选物体;
			}
			break;
		}
		case E_物体类型::t_线段: {
			//for (uint32 i = 0; i < me->m_间接->m_Mem.m_大小; ++i) {
			//	S_线拾取 info = f_surface_线段相交(me, mat, 视线起点方向相机位置[0], 视线起点方向相机位置[1], 当前拾取距离, i);
			//	if (info.相交距离 < 线拾取距离) {
			//		if (当前拾取距离 < 物体拾取信息.相交距离) {
			//			物体拾取信息.相交距离 = 当前拾取距离;
			//			物体拾取信息.实例ID = 待选物体->m_实例ID;
			//			物体拾取信息.物体 = 待选物体;
			//		}
			//	}
			//}
			break;
		}

		default:
			break;
	}


	if (物体拾取信息.物体) {
		//物体拾取信息.相交距离 *= f_mesh_get网格元素绘制属性(me).m_DepthScale;
	}

	return 物体拾取信息;
}

float32 f_scene_拾取物体网格(S_物体* 待选物体, uint32 槽, const vec3 射线[3]) {
	Mat44f mat[2] = {f_bm_at<Mat44f>(待选物体->m_变换矩阵), 0};
	auto& pack = f_ob_get数据(待选物体, 槽);
	auto 拾取信息 = f_surface_射线面相交(pack.m_Mesh, mat, 射线[0], 射线[1]);

	if (拾取信息.面索引 >= 0) {
		return 拾取信息.相交宽度;
	}
	return -1;
}

vec3 f_scene_构建屏幕射线(vec3 坐标, const S_摄像机& camera, const S_Rect2Df& rect, vec3 射线[2]) {
	vec3 dir;
	if (camera.m_投影模式 == E_投影模式::e_透视) {
		坐标.z = 1;
		射线[0] = f_UpProject还原空间顶点(坐标, *(Mat44f*)&camera.m_相机投影矩阵, *(Mat44f*)&camera.m_相机视图矩阵, rect);
		坐标.z = 0;
		射线[1] = f_UpProject还原空间顶点(坐标, *(Mat44f*)&camera.m_相机投影矩阵, *(Mat44f*)&camera.m_相机视图矩阵, rect);

		dir = vec_normalize2(射线[1] - 射线[0]);
		//dir = (射线[1] - 射线[0]);
	}
	else {
		坐标.z = 1.0;
		射线[0] = f_UpProject还原空间顶点(坐标, *(Mat44f*)&camera.m_相机投影矩阵, *(Mat44f*)&camera.m_相机视图矩阵, rect);
		坐标.z = -1.0;
		射线[1] = f_UpProject还原空间顶点(坐标, *(Mat44f*)&camera.m_相机投影矩阵, *(Mat44f*)&camera.m_相机视图矩阵, rect);

		dir = vec_normalize2(射线[1] - 射线[0]);
	}
	return dir;
}

S_物体拾取信息 f_scene_拾取网格点(const std::vector<S_物体*>& 物体, const S_摄像机& camera, const S_Rect2Df& rect, const vec2& 屏幕坐标, float32 拾取最小距离) {
	Mat44f mat[4];

	S_物体拾取信息 物体拾取信息{ nullptr, -1, 100000000, 6.0f , 0xffffffff, 0};
	/*vec3 相机位置 = f_camera_get眼睛位置(camera);

	mat[1] = *(Mat44f*)&camera.m_相机投影;
	mat[2] = *(Mat44f*)&camera.m_相机位置矩阵;
	mat[3] = *(Mat44f*)&camera.m_相机逆矩阵;

	Mat44f* 当前矩阵prt; // = 父级变换;

	for (auto& e : 物体) {
		当前矩阵prt = f_buf_Mat44_ptr(e->m_变换矩阵);

		mat[0] = 当前矩阵prt[e->m_实例ID];

		auto me = f_ob_getMesh(e);
		float32 拾取距离 = 拾取最小距离;
		uint32 index = 0xffffffff;
		auto 点 = f_surface_屏幕拾取点(me, mat, 屏幕坐标, rect, 6);

		if (index != 0xffffffff) {
			S_物体拾取信息 新拾取;
			新拾取.相交深度 = length(点 - 相机位置);
			新拾取.平面距离 = 拾取距离;
			新拾取.实例ID = 0;
			新拾取.物体 = e;
			新拾取.拾取模式 = 1;
			新拾取.元素索引 = index;

			f_scene_对比拾取信息(物体拾取信息, 新拾取, camera.m_投影模式);
		}
	}*/

	return 物体拾取信息;
}

S_物体拾取信息 f_scene_拾取网格面(const std::vector<S_物体*>& 物体, const S_摄像机& camera, const S_Rect2Df& rect, const vec2& 屏幕坐标) {
	std::vector<S_物体*> pickObjs;

	vec3 射线[2];
	vec3 射线方向 = f_scene_构建屏幕射线(_Vec3(屏幕坐标, 0.001f), camera, rect, 射线);

	vec3 交点 = {};
	vec3 相机位置 = f_camera_get眼睛位置(camera);
	S_物体拾取信息 物体拾取信息{ nullptr, -1, 100000000, 6 };

	if (camera.m_投影模式 == E_投影模式::e_正交) {
		相机位置 = -相机位置;
	}

	for (auto& e : 物体) {
		S_物体拾取信息 新拾取信息 = f_scene_射线拾取物体面(e, 射线[0], 射线方向, nullptr, nullptr, camera, 0, 相机位置);
		f_scene_对比拾取信息(物体拾取信息, 新拾取信息);
	}

	return 物体拾取信息;
}

void f_scene_添加回调对象(S_Scene* scene, S_场景回调* call) {
	scene->m_更新回调.push_back(call);
}

void f_scene_删除回调对象(S_Scene* scene, S_场景回调* call) {
	for (auto it = scene->m_更新回调.begin(); it != scene->m_更新回调.end(); ++it) {
		if (*it == call) {
			scene->m_更新回调.erase(it);
			break;
		}
	}
}




//S_实例拾取信息 f_scene_射线拾取物体实例(S_物体* obj, const vec3& s, const vec3& e) {
//	S_实例拾取信息 物体实例ID = { -1, 100000000 };
//	vec3 交点 = {};
//	vec3 dir = vec_normalize2(vec_sub(e, s));
//
//	auto* m = f_ob_fromMesh(obj, DEF_网格主数据层);
//	if (!m) return 物体实例ID;
//
//
//	float32 当前距离 = 100000000;
//	//Mat44f* mat_prt = f_buf_map板载缓存<Mat44f>(obj->m_变换矩阵);
//	Mat44f mat_prt[2] = { *f_buf_Mat44_ptr(obj->m_变换矩阵), {}};
//	
//	uint32 num = obj->m_变换矩阵.m_Mem.m_大小;
//
//	switch (obj->m_Type) {
//	case E_物体类型::t_骨骼:
//	case E_物体类型::t_骨架: {
//		if (obj->m_骨架) {
//			//float32* scale_prt = f_buf_F32_ptr(obj->m_骨架->m_骨骼长度);
//
//			for (uint32 i = 0; i < num; ++i) {
//				//mat = (float32*)&mat_prt[i];
//				if (f_surface_射线面相交(m, mat_prt, s, dir, 交点, 当前距离)) {
//					if (当前距离 <= 物体实例ID.相交距离) {
//						物体实例ID.相交距离 = 当前距离;
//						物体实例ID.实例ID = i;
//					}
//				}
//			}
//		}
//		break;
//	}
//
//	default:
//		for (uint32 i = 0; i < num; ++i) {
//			//mat = (float32*)&mat_prt[i];
//			if (f_surface_射线面相交(m, mat_prt, s, dir, 交点, 当前距离)) {
//				if (当前距离 <= 物体实例ID.相交距离) {
//					物体实例ID.相交距离 = 当前距离;
//					物体实例ID.实例ID = i;
//				}
//			}
//		}
//		break;
//	}
//
//	//f_buf_unmap板载缓存(obj->m_变换矩阵);
//	return 物体实例ID;
//}




void f_scene_渲染器GPU内存映射() {
	//return;
	for (auto& e : g场景容器) {
		if(e.second->m_光追后端) e.second->m_光追后端->f_mapGPU参数();
	}
}

void f_scene_渲染器GPU内存解映射() {
	//return;
	for (auto& e : g场景容器) {
		if (e.second->m_光追后端) e.second->m_光追后端->f_unmapGPU参数();
	}
}

void f_scene_渲染器分配GPU内存() {
	//return;
	for (auto& e : g场景容器) {
		if (e.second->m_光追后端) e.second->m_光追后端->f_resizeGPU参数();
	}
}

void f_scene_物体GPU内存分配() {

	/*if (S_物体::g_包围盒物体->m_变换矩阵->m_mappedPtr) {
		S_物体::g_包围盒物体->m_变换矩阵->f_unmap();
	}
	if (S_物体::g_包围盒物体->m_变换矩阵->m_分配器.maxNum) {
		f_buf_resize(S_物体::g_包围盒物体->m_变换矩阵, S_物体::g_包围盒物体->m_变换矩阵->m_分配器.maxNum);
	}
	S_物体::g_包围盒物体->m_变换矩阵->f_map();*/


}


uint32 f_scene_渲染器分配平行光内存(S_Scene* scene, uint32 num) {
	return f_buf_galloc(f_buf_getGlobal().m_平行光缓冲区, num).m_偏移;
}

S_GPU内存块 f_scene_渲染器分配点光源内存(S_Scene* scene, uint32 num) {
	scene->m_光追后端->m_渲染配置.点光源数量 = f_buf_getGlobal().m_点光源缓冲区->m_Size + num;
	//(*scene->m_光追后端->m_mapPtr_渲染帧数据).m_PointLightNum += num;
	return f_bm_alloc(f_buf_getGlobal().m_点光源缓冲区, num);
}

uint32 f_scene_渲染器分配区域光内存(S_Scene* scene, uint32 num) {
	return f_buf_galloc(f_buf_getGlobal().m_区域光缓冲区, num).m_偏移;
}

uint32 f_scene_渲染器分配聚光灯内存(S_Scene* scene, uint32 num) {
	return f_buf_galloc(f_buf_getGlobal().m_聚光灯缓冲区, num).m_偏移;
}



void f_scene_渲染器设置平行光(S_Scene* scene, uint32 ID, const S_LightParallel& ligth) {
	((S_LightParallel*)f_buf_getGlobal().m_平行光缓冲区->m_mappedPtr)[ID] = ligth;
}

void f_scene_渲染器设置平行光启用(S_Scene* scene, uint32 ID, const bool e) {
	((S_LightParallel*)f_buf_getGlobal().m_平行光缓冲区->m_mappedPtr)[ID].m_enable = e;
}

void f_scene_渲染器设置点光源(S_Scene* scene, uint32 ID, const S_LightPoint& ligth) {
	((S_LightPoint*)f_buf_getGlobal().m_点光源缓冲区->m_mappedPtr)[ID] = ligth;
}

void f_scene_渲染器设置点光源启用(S_Scene* scene, uint32 ID, const bool e) {
	((S_LightPoint*)f_buf_getGlobal().m_点光源缓冲区->m_mappedPtr)[ID].m_enable = e;
}

void f_scene_渲染器设置聚光灯(S_Scene* scene, uint32 ID, const S_LightSpot& ligth) {
	((S_LightSpot*)f_buf_getGlobal().m_聚光灯缓冲区->m_mappedPtr)[ID] = ligth;
}

void f_scene_渲染器设置聚光灯启用(S_Scene* scene, uint32 ID, const bool e) {
	((S_LightSpot*)f_buf_getGlobal().m_聚光灯缓冲区->m_mappedPtr)[ID].m_enable = e;
}

void f_scene_渲染器设置区域光(S_Scene* scene, uint32 ID, const S_LightArea& ligth) {
	((S_LightArea*)f_buf_getGlobal().m_区域光缓冲区->m_mappedPtr)[ID] = ligth;
}

void f_scene_渲染器设置区域光启用(S_Scene* scene, uint32 ID, const bool e) {
	((S_LightArea*)f_buf_getGlobal().m_区域光缓冲区->m_mappedPtr)[ID].m_enable = e;
}

//S_GPU内存块索引 f_scene_渲染器创建点光源(S_Scene* scene) {
//	return f_buf_alloc(S_全局缓存::m_点光源缓冲区, 1);
//	return S_GPU内存块索引();
//}




void f_scene_渲染器启用预览(S_Scene* scene) {
	static uint32 位 = (1 << E_物体网格元素类型::e_MT_预览);
	scene->m_光追后端->g_物体全局显示模式 = E_物体视口显示::e_OVS_预览;

	f_render_刷新渲染(scene);
}

void f_scene_渲染器关闭预览(S_Scene* scene) {
	static uint32 位 = (0xffffffff ^ (1 << E_物体网格元素类型::e_MT_预览));
	scene->m_光追后端->g_物体全局显示模式 = 0;

	f_render_刷新渲染(scene);
}


void f_scene_渲染器启用渲染(S_Scene* scene) {
	static uint32 位 = (1 << E_物体网格元素类型::e_MT_渲染);
	scene->m_光追后端->g_物体全局显示模式 = E_物体视口显示::e_OVS_渲染;

	f_render_刷新渲染(scene);
}

void f_scene_渲染器关闭渲染(S_Scene* scene) {
	static uint32 位 = (0xffffffff ^ (1 << E_物体网格元素类型::e_MT_渲染));
	scene->m_光追后端->g_物体全局显示模式 = 0;

	f_render_刷新渲染(scene);
}

void f_scene_set渲染器渲染预览模式(S_Scene* scene, E_RenderLayerType 渲染预览模式) {
	uint32 mask = scene->m_光追后端->m_mapPtr_渲染帧数据->m_OutLayer_PreviewMode & 0x0000ffff;
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_OutLayer_PreviewMode = DEF_RF_PM_PreviewFlag | (1<<(渲染预览模式+16));

	f_render_刷新渲染(scene);
}

void f_scene_set渲染器渲染层(S_Scene* scene, uint32 layers) {
	scene->m_光追后端->m_mapPtr_渲染帧数据->m_OutLayer_PreviewMode |= (layers);
	f_render_刷新渲染(scene);
}





static void f_从场景构建底层光追加速结构(S_物体* ob) {
	
	f_ob_构建底层光追加速结构(ob);

	for (auto& son : ob->m_子物体) {
		f_从场景构建底层光追加速结构(static_cast<S_物体*>(son));
	}
}

static void f_从场景构建顶层光追加速结构(S_物体* ob, S_渲染层& 渲染层, uint32& 实例偏移) {
	f_ob_构建光追实例加速结构(ob, 渲染层, 1, 1 << 16 | 0, 实例偏移);

	for (auto& son : ob->m_子物体) {
		f_从场景构建顶层光追加速结构(static_cast<S_物体*>(son), 渲染层, 实例偏移);
	}
}


void f_scene_构建光追加速结构(S_Scene* scene) {
	if (scene->m_重新录制绘图命令) {
		for (auto& e : scene->m_物体set) {
			f_从场景构建底层光追加速结构(e);
		}
	}

	uint32 实例偏移 = 0;
	S_渲染层& 渲染层 = *scene->m_默认渲染世界->m_层[0];
	for (auto& e : scene->m_物体set) {
		f_从场景构建顶层光追加速结构(e, 渲染层, 实例偏移);
	}
	
	if (实例偏移) {
		f_df_构建顶层光追加速(渲染层, 实例偏移);
	}
	f_world_更新绑定(scene->m_默认渲染世界);
}


void f_render_刷新渲染(S_Scene* scene) {
	scene->m_光追后端->f_重置渲染帧记录();
}

void f_render_绑定参数(S_摄像机* camera, GLSL_RenderFrame& 帧渲染参数, S_纹理& tex, S_渲染世界* 世界, S_光追后端* 光追后端) {
	if (光追后端->m_重新编译线管) {
		光追后端->f_重构材质线管();
		光追后端->m_重新编译线管 = false;
	}


	f_buf_copy板载缓存(光追后端->m_投影矩阵, camera->m_投影矩阵);
	f_纹理槽_设置纹理集(世界->m_输出纹理槽, 世界->m_输出纹理, 0, DEF_BINDING_RayTexturesWriteLayers);
	f_纹理集_刷新所有纹理信息(世界->m_输出纹理);
	//*f_buf_全局GPU参数指针_ptr(S_全局缓存::g_全局绑定参数) = f_df_全局GPU参数();

	f_render_更新参数(帧渲染参数, 世界, 光追后端);

	//帧渲染参数.m_Frame = 0;
	//(*光追后端->m_mapPtr_渲染帧数据) = 帧渲染参数;
	//(*光追后端->m_mapPtr_渲染帧数据).m_PointLightNum = 光追后端->m_渲染配置.点光源数量;
	//(*光追后端->m_mapPtr_渲染帧数据).m_ViewSize = 帧渲染参数.m_ViewSize;
	//(*光追后端->m_mapPtr_渲染帧数据).m_Address_RtOb = f_buf_getAddress2(世界->m_物体指针);



	光追后端->m_参数布局.m_参数槽[0] = 世界->m_光追描述集;
	光追后端->m_参数布局.m_参数类型[0] = E_板载缓存类型::e_光追BVH;
	光追后端->m_参数布局.m_绑定位置[0] = 0;
	光追后端->m_参数布局.m_绑定数量[0] = f_ob_get光追加速结构描述集数量(世界->m_光追描述集);



	光追后端->m_参数布局.m_参数槽[1] = &tex;
	光追后端->m_参数布局.m_参数类型[1] = E_板载缓存类型::e_IMAGE;
	光追后端->m_参数布局.m_绑定位置[1] = DEF_BINDING_Render_Image;
	光追后端->m_参数布局.m_绑定数量[1] = 1;

	光追后端->m_参数布局.m_参数槽[2] = 光追后端->m_投影矩阵;
	光追后端->m_参数布局.m_参数类型[2] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[2] = DEF_BINDING_Render_Camera;
	光追后端->m_参数布局.m_绑定数量[2] = 1;

	光追后端->m_参数布局.m_参数槽[3] = f_buf_getGlobal().m_场景物体网格属性;
	光追后端->m_参数布局.m_参数类型[3] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[3] = DEF_ObMeshBindID;
	光追后端->m_参数布局.m_绑定数量[3] = 1;

	光追后端->m_参数布局.m_参数槽[4] = f_buf_getGlobal().g_材质;
	光追后端->m_参数布局.m_参数类型[4] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[4] = DEF_MaterialsBindID;
	光追后端->m_参数布局.m_绑定数量[4] = 1;


	光追后端->m_参数布局.m_参数槽[5] = 光追后端->m_帧渲染信息;
	光追后端->m_参数布局.m_参数类型[5] = E_板载缓存类型::e_UBO;
	光追后端->m_参数布局.m_绑定位置[5] = DEF_RenderFrameBindID;
	光追后端->m_参数布局.m_绑定数量[5] = 1;

	光追后端->m_参数布局.m_参数槽[6] = f_buf_getGlobal().m_平行光缓冲区;
	光追后端->m_参数布局.m_参数类型[6] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[6] = DEF_ParallelLightBindID;
	光追后端->m_参数布局.m_绑定数量[6] = 1;

	光追后端->m_参数布局.m_参数槽[7] = 光追后端->f_get纹理(E_纹理分组类型::e_2D纹理);
	光追后端->m_参数布局.m_参数类型[7] = E_板载缓存类型::e_SAMPLER_Array;
	光追后端->m_参数布局.m_绑定位置[7] = DEF_TexturesBindID;
	光追后端->m_参数布局.m_绑定数量[7] = 光追后端->f_get纹理数量(E_纹理分组类型::e_2D纹理);

	光追后端->m_参数布局.m_参数槽[8] = f_buf_getGlobal().m_几何属性;
	光追后端->m_参数布局.m_参数类型[8] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[8] = DEF_BINDING_Render_Geom;
	光追后端->m_参数布局.m_绑定数量[8] = 1;

	光追后端->m_参数布局.m_参数槽[9] = f_buf_getGlobal().m_全局绑定参数指针;
	光追后端->m_参数布局.m_参数类型[9] = E_板载缓存类型::e_SSBO;
	光追后端->m_参数布局.m_绑定位置[9] = DEF_BINDING_Render_GlobalParam;
	光追后端->m_参数布局.m_绑定数量[9] = 1;

	光追后端->m_参数布局.m_参数槽[10] = 光追后端->f_get纹理(E_纹理分组类型::e_字符纹理);
	光追后端->m_参数布局.m_参数类型[10] = E_板载缓存类型::e_SAMPLER_Array;
	光追后端->m_参数布局.m_绑定位置[10] = DEF_BINDING_RayArrayTexturesBindID;
	光追后端->m_参数布局.m_绑定数量[10] = 光追后端->f_get纹理数量(E_纹理分组类型::e_字符纹理);
	

	光追后端->m_参数布局.m_纹理槽 = &世界->m_输出纹理槽;
	
	f_df_upGPU参数(光追后端->m_Ctx->m_逻辑设备.设备, 光追后端->m_GPU参数设置, 光追后端->m_参数布局, false);
}

void f_render_更新参数(GLSL_RenderFrame& 帧渲染参数, S_渲染世界* 世界, S_光追后端* 光追后端) {
	*f_buf_全局GPU参数指针_ptr(f_buf_getGlobal().g_全局绑定参数) = f_df_全局GPU参数();

	//帧渲染参数.m_Frame = 0;
	(*光追后端->m_mapPtr_渲染帧数据) = 帧渲染参数;
	(*光追后端->m_mapPtr_渲染帧数据).m_PointLightNum = 光追后端->m_渲染配置.点光源数量;
	(*光追后端->m_mapPtr_渲染帧数据).m_ViewSize = 帧渲染参数.m_ViewSize;
	(*光追后端->m_mapPtr_渲染帧数据).m_Address_RtOb = f_buf_getAddress2(世界->m_物体指针);

}








